package com.liangchen.asperf;

import android.app.Activity;
import android.app.Application;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.FrameMetrics;
import android.view.Window;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.liangchen.astools.AsManager;
import com.liangchen.astools.utils.AsLog;

import static android.view.FrameMetrics.TOTAL_DURATION;

@RequiresApi(api = Build.VERSION_CODES.N)
public class FpsTracker implements BaseTracker, Application.ActivityLifecycleCallbacks, Window.OnFrameMetricsAvailableListener {
    private static final String TAG = "cdgtest-FpsTracker";
    private Handler workHandler = AsManager.getmWorkerHandler();
    private Activity mCurrentActivity;
    private Activity mLastActivity = null;
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public void start() {
      /* if (mCurrentActivity != null){
            mCurrentActivity.getWindow().addOnFrameMetricsAvailableListener(this,workHandler);
       }*/
    }

    @Override
    public void stop() {

    }

    @Override
    public void dump() {

    }

    @Override
    public void report() {

    }


    @Override
    public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {

    }

    @Override
    public void onActivityStarted(@NonNull Activity activity) {
        AsLog.i(TAG,activity.getLocalClassName()+": onStart()");

    }

    @Override
    public void onActivityResumed(@NonNull Activity activity) {
        AsLog.i(TAG,activity.getLocalClassName()+": onResume()");
        if (mLastActivity == null || mLastActivity != activity ){
            activity.getWindow().addOnFrameMetricsAvailableListener(this, workHandler);
            mLastActivity = activity;
        }
    }

    @Override
    public void onActivityPaused(@NonNull Activity activity) {
        AsLog.i(TAG,activity.getLocalClassName()+": onPause()");

    }

    @Override
    public void onActivityStopped(@NonNull Activity activity) {
        AsLog.i(TAG,activity.getLocalClassName()+": onStop()");
    }

    @Override
    public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(@NonNull Activity activity) {
        AsLog.i(TAG,activity.getLocalClassName()+": onDestroy()");

    }


    @Override
    public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics, int dropCountSinceLastInvocation) {

        FrameMetrics fm = new FrameMetrics(frameMetrics);

        // 1. 动画执行回调时间, 单位纳秒
        AsLog.i("FrameMetrics", "ANIMATION_DURATION : " +
                fm.getMetric(FrameMetrics.ANIMATION_DURATION));

        // 2. 向 GPU 发送绘制命令花费的时间, 单位纳秒
        AsLog.i("FrameMetrics", "COMMAND_ISSUE_DURATION : " +
                fm.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION));

        // 3. 将组件树 ( View Hierarchy ) 转为显示列表 ( DisplayLists )
        // 计算过程所花费的时间, 单位纳秒
        AsLog.i("FrameMetrics", "DRAW_DURATION : " +
                fm.getMetric(FrameMetrics.DRAW_DURATION));

        // 4. 绘制的该帧是否是第一帧, 0 是, 1 不是
        // 第一帧渲染会慢一些
        // 第一帧不会引发动画中的跳帧问题, 这些问题都会被窗口动画隐藏
        // 不必进行显示过程中的 jank 计算
        AsLog.i("FrameMetrics", "FIRST_DRAW_FRAME : " +
                fm.getMetric(FrameMetrics.FIRST_DRAW_FRAME));

        // 5. 处理输入事件花费的时间, 单位纳秒
        AsLog.i("FrameMetrics", "INPUT_HANDLING_DURATION : " +
                fm.getMetric(FrameMetrics.INPUT_HANDLING_DURATION));

        // 6. 该值是个时间戳, 表示该帧的 vsync 信号发出时间
        // 这个时间是当前帧的预期开始时间
        // 如果该时间与 VSYNC_TIMESTAMP 时间戳不同
        // 那么说明 UI 线程被阻塞了, 没有及时响应 vsync 信号
        AsLog.i("FrameMetrics", "INTENDED_VSYNC_TIMESTAMP : " +
                fm.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP));

        // 7. 组件树 ( view hierarchy ) 测量 ( measure ) 和摆放 ( layout ) 花费的时间
        // 单位 纳秒
        AsLog.i("FrameMetrics", "LAYOUT_MEASURE_DURATION : " +
                fm.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION));

        // 8. CPU 传递多维向量图形数据给 GPU 花费的时间, 单位纳秒
        AsLog.i("FrameMetrics", "SWAP_BUFFERS_DURATION : " +
                fm.getMetric(FrameMetrics.SWAP_BUFFERS_DURATION));

        // 9. 显示列表 ( DisplayLists ) 与显示线程同步花费的时间, 单位纳秒
        AsLog.i("FrameMetrics", "SYNC_DURATION : " +
                fm.getMetric(FrameMetrics.SYNC_DURATION));

        // 10. CPU 渲染到传递到 GPU 所用的总时间, 上述所花费的有意义的时间之和
        // 单位纳秒
        AsLog.i("FrameMetrics", "TOTAL_DURATION : " +
                fm.getMetric(FrameMetrics.TOTAL_DURATION));

        // 11. UI 线程响应并开始处理渲染的等待时间, 一般是 0, 如果大于 0 说明出问题了
        AsLog.i("FrameMetrics", "UNKNOWN_DELAY_DURATION : " +
                fm.getMetric(FrameMetrics.UNKNOWN_DELAY_DURATION));

        // 12. vsync 信号发出的时间戳, 该时刻 GPU 应该进行绘制, 间隔 16ms
        // 同时 CPU 开始渲染
        AsLog.i("FrameMetrics", "VSYNC_TIMESTAMP : " +
                fm.getMetric(FrameMetrics.VSYNC_TIMESTAMP));


        long total = frameMetrics.getMetric(TOTAL_DURATION);
        AsLog.i(TAG,window.getDecorView().toString()+": dropCountSinceLastInvocation:"+dropCountSinceLastInvocation+",total:"+total);
    }
}
